package scheduler

import (
	"context"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"

	"go-agent/pkg/client"
	"go-agent/pkg/collector"
	"go-agent/pkg/config"
	"go-agent/pkg/logger"
	"go-agent/pkg/services"
	"go-agent/pkg/transport"

	"github.com/robfig/cron/v3"
)

// ItemScheduler 监控项调度器
type ItemScheduler struct {
	ItemID                int64
	ItemName              string
	ItemKey               string
	InfoType              int
	UpdateIntervalSeconds int
	Timeout               int
	Intervals             []services.IntervalSchedule // 复杂时间调度配置
	CronID                cron.EntryID                // cron任务ID
	ticker                *time.Ticker                // 用于简单时间间隔
	stopChan              chan struct{}
	running               bool
	scheduleMode          string // 调度模式: "simple", "complex"
	currentInterval       int    // 当前生效的间隔秒数
}

// Scheduler 任务调度器
type Scheduler struct {
	cron             *cron.Cron
	config           *config.Config
	systemCollector  *collector.SystemCollector
	snmpCollector    *collector.SNMPCollector
	scriptCollector  *collector.ScriptCollector
	commandCollector *collector.CommandCollector // 新增命令执行采集器
	nginxCollector   *collector.NginxCollector   // Nginx采集器
	zookeeperCollector *collector.ZookeeperCollector // Zookeeper采集器
	httpTransport    *transport.HTTPTransport
	grpcTransport    *transport.GRPCTransport
	// 新增API相关服务
	apiClient        *client.DeviceMonitorClient
	registerService  *services.RegisterService
	heartbeatService *services.HeartbeatService
	configManager    *services.ConfigManager
	metricsSender    *services.MetricsSender
	// 内置键管理器
	builtinKeyManager *collector.BuiltinKeyManager
	// 监控项调度器
	itemSchedulers map[int64]*ItemScheduler
	ctx            context.Context
	cancel         context.CancelFunc
	wg             sync.WaitGroup
	mu             sync.RWMutex
	running        bool
}

// New 创建新的调度器
func New() *Scheduler {
	ctx, cancel := context.WithCancel(context.Background())

	return &Scheduler{
		cron:           cron.New(cron.WithSeconds()),
		ctx:            ctx,
		cancel:         cancel,
		itemSchedulers: make(map[int64]*ItemScheduler),
	}
}

// Start 启动调度器
func (s *Scheduler) Start(cfg *config.Config) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	if s.running {
		return fmt.Errorf("调度器已在运行")
	}

	s.config = cfg

	// 初始化采集器
	if err := s.initCollectors(); err != nil {
		return fmt.Errorf("初始化采集器失败: %v", err)
	}

	// 初始化传输器
	if err := s.initTransporters(); err != nil {
		return fmt.Errorf("初始化传输器失败: %v", err)
	}

	// 初始化内置键管理器
	if err := s.initBuiltinKeyManager(); err != nil {
		logger.Warnf("初始化内置键管理器失败: %v", err)
		// 这里只是警告，不阻止启动
	}

	// 首先添加基础的定时任务（系统指标采集等），这些不依赖API
	if err := s.addScheduledJobs(); err != nil {
		return fmt.Errorf("添加定时任务失败: %v", err)
	}

	// 初始化API服务
	if err := s.initAPIServices(); err != nil {
		logger.Warnf("初始化API服务失败: %v，将仅使用本地采集功能", err)
		// 不返回错误，让基础功能继续运行
	} else {
		// 并行启动API服务，避免阻塞主流程
		go func() {
			defer func() {
				if r := recover(); r != nil {
					logger.Errorf("API服务启动出现panic: %v", r)
				}
			}()

			if err := s.startAPIServices(); err != nil {
				logger.Errorf("启动API服务失败: %v", err)
			} else {
				logger.Info("API服务启动成功")
				logger.Info("等待配置加载完成后启动监控项调度器...")
				// 注意: 监控项调度器将通过配置更新回调自动启动
			}
		}()
	}

	// 启动cron调度器
	s.cron.Start()
	s.running = true

	// 增加一个长期运行的任务到WaitGroup，确保Wait()会阻塞
	s.wg.Add(1)
	go func() {
		defer s.wg.Done()
		// 等待上下文取消
		<-s.ctx.Done()
		logger.Debug("调度器主循环已停止")
	}()

	logger.Info("调度器已启动")

	return nil
}

// Stop 停止调度器
func (s *Scheduler) Stop() error {
	s.mu.Lock()
	defer s.mu.Unlock()

	if !s.running {
		return nil
	}

	// 停止cron调度器
	s.cron.Stop()

	// 停止API服务
	s.stopAPIServices()

	// 停止监控项调度器
	s.stopItemSchedulers()

	// 取消上下文
	s.cancel()

	// 等待所有任务完成
	s.wg.Wait()

	s.running = false
	logger.Info("调度器已停止")

	return nil
}

// Wait 等待调度器停止
func (s *Scheduler) Wait() {
	s.wg.Wait()
}

// initCollectors 初始化采集器
func (s *Scheduler) initCollectors() error {
	// 初始化系统采集器
	s.systemCollector = collector.NewSystemCollector(s.config.Collect.System.Enabled)

	// 初始化SNMP采集器
	s.snmpCollector = collector.NewSNMPCollector(
		s.config.Collect.SNMP.Enabled,
		s.config.Collect.SNMP.Targets,
		s.config.Collect.SNMP.Community,
		s.config.Collect.SNMP.Version,
		s.config.Collect.SNMP.Port,
		s.config.Agent.Timeout,
	)

	// 初始化脚本采集器
	s.scriptCollector = collector.NewScriptCollector(
		s.config.Collect.Script.Enabled,
		s.config.Collect.Script.Scripts,
		s.config.Collect.Script.Timeout,
	)

	// 初始化Nginx采集器
	nginxConfig := collector.NginxConfig{
		Enabled:       s.config.Collect.Nginx.Enabled,
		StatusURL:     s.config.Collect.Nginx.StatusURL,
		Timeout:       s.config.Collect.Nginx.Timeout,
		SlowThreshold: s.config.Collect.Nginx.SlowThreshold,
		UserAgent:     s.config.Collect.Nginx.UserAgent,
		Headers:       s.config.Collect.Nginx.Headers,
	}
	s.nginxCollector = collector.NewNginxCollector(nginxConfig)

	// 初始化Zookeeper采集器
	zookeeperConfig := collector.ZookeeperConfig{
		Enabled:        s.config.Collect.Zookeeper.Enabled,
		Host:           s.config.Collect.Zookeeper.Host,
		Port:           s.config.Collect.Zookeeper.Port,
		Timeout:        s.config.Collect.Zookeeper.Timeout,
		Commands:       s.config.Collect.Zookeeper.Commands,
		TrackHistory:   s.config.Collect.Zookeeper.TrackHistory,
		MaxHistorySize: s.config.Collect.Zookeeper.MaxHistorySize,
	}
	s.zookeeperCollector = collector.NewZookeeperCollector(zookeeperConfig)

	return nil
}

// initBuiltinKeyManager 初始化内置键管理器
func (s *Scheduler) initBuiltinKeyManager() error {
	s.builtinKeyManager = collector.NewBuiltinKeyManager()
	allKeys := s.builtinKeyManager.GetAllKeys()
	logger.Infof("内置键管理器初始化成功，支持 %d 个内置监控项", len(allKeys))

	// 打印所有支持的键
	for _, key := range allKeys {
		logger.Debugf("支持的内置键: %s - %s", key.Key, key.Description)
	}

	return nil
}

// initTransporters 初始化传输器
func (s *Scheduler) initTransporters() error {
	// 初始化HTTP传输器
	s.httpTransport = transport.NewHTTPTransport(
		s.config.Transport.HTTP.Enabled,
		s.config.Transport.HTTP.URL,
		s.config.Transport.HTTP.Method,
		s.config.Transport.HTTP.Headers,
		s.config.Agent.Timeout,
	)

	// 初始化gRPC传输器
	s.grpcTransport = transport.NewGRPCTransport(
		s.config.Transport.GRPC.Enabled,
		s.config.Transport.GRPC.Server,
		s.config.Transport.GRPC.Port,
		s.config.Agent.Timeout,
	)

	// 如果启用gRPC，尝试连接
	if s.config.Transport.GRPC.Enabled {
		if err := s.grpcTransport.Connect(s.ctx); err != nil {
			logger.Warnf("gRPC连接失败: %v", err)
		}
	}

	return nil
}

// addScheduledJobs 添加定时任务
func (s *Scheduler) addScheduledJobs() error {
	// 计算采集间隔（秒）
	intervalSeconds := int(s.config.Agent.Interval.Seconds())
	if intervalSeconds < 1 {
		intervalSeconds = 30 // 默认30秒
	}

	// 添加系统指标采集任务
	if s.config.Collect.System.Enabled {
		cronSpec := fmt.Sprintf("*/%d * * * * *", intervalSeconds)
		_, err := s.cron.AddFunc(cronSpec, s.collectAndSendSystemMetrics)
		if err != nil {
			return fmt.Errorf("添加系统指标采集任务失败: %v", err)
		}
		logger.Infof("已添加系统指标采集任务，间隔: %s", s.config.Agent.Interval)
	}

	// 添加SNMP采集任务
	if s.config.Collect.SNMP.Enabled {
		cronSpec := fmt.Sprintf("*/%d * * * * *", intervalSeconds)
		_, err := s.cron.AddFunc(cronSpec, s.collectAndSendSNMPMetrics)
		if err != nil {
			return fmt.Errorf("添加SNMP采集任务失败: %v", err)
		}
		logger.Infof("已添加SNMP采集任务，间隔: %s", s.config.Agent.Interval)
	}

	// 添加脚本执行任务
	if s.config.Collect.Script.Enabled {
		cronSpec := fmt.Sprintf("*/%d * * * * *", intervalSeconds)
		_, err := s.cron.AddFunc(cronSpec, s.collectAndSendScriptMetrics)
		if err != nil {
			return fmt.Errorf("添加脚本执行任务失败: %v", err)
		}
		logger.Infof("已添加脚本执行任务，间隔: %s", s.config.Agent.Interval)
	}

	return nil
}

// collectAndSendSystemMetrics 采集并发送系统指标
func (s *Scheduler) collectAndSendSystemMetrics() {
	s.wg.Add(1)
	defer s.wg.Done()

	ctx, cancel := context.WithTimeout(s.ctx, s.config.Agent.Timeout)
	defer cancel()

	logger.Debug("开始执行系统指标采集和上报任务")

	// 采集系统指标
	metrics, err := s.systemCollector.Collect(ctx)
	if err != nil {
		logger.Errorf("采集系统指标失败: %v", err)
		return
	}

	logger.Debugf("系统指标采集成功: CPU=%.2f%%, Memory=%.2f%%", metrics.CPU.UsagePercent, metrics.Memory.UsagePercent)

	// 优先使用数据中心API上报（如果可用）
	if s.apiClient != nil && s.apiClient.GetAgentID() != "" {
		logger.Debug("使用数据中心API上报系统指标")
		s.sendSystemMetricsToDataCenter(ctx, metrics)
	} else {
		logger.Warn("⚠️ 数据中心API不可用（AgentID为空），跳过系统指标上报")
		logger.Debug("等待Agent注册完成后，数据将通过动态监控项调度器上报")
		// 不再使用传统HTTP传输，避免与动态监控项调度器的数据格式冲突
		// 数据将在Agent注册完成后通过正确的API端点和格式上报
	}
}

// sendSystemMetricsToDataCenter 使用数据中心API发送系统指标
// 采用智能策略：如果动态调度器没有启动，则使用硬编码上报作为备用
func (s *Scheduler) sendSystemMetricsToDataCenter(ctx context.Context, metrics *collector.SystemMetrics) {
	// 检查是否有动态监控项调度器在运行
	s.mu.RLock()
	runningSchedulersCount := 0
	totalSchedulersCount := len(s.itemSchedulers)
	for _, scheduler := range s.itemSchedulers {
		if scheduler.running {
			runningSchedulersCount++
		}
	}
	s.mu.RUnlock()

	if runningSchedulersCount > 0 {
		logger.Debugf("动态监控项调度器已启动 (%d/%d 运行中)，跳过硬编码上报避免重复", runningSchedulersCount, totalSchedulersCount)
		return
	}

	if totalSchedulersCount > 0 {
		logger.Warnf("⚠️ 动态监控项调度器已配置但未运行 (%d 个调度器)，等待调度器启动", totalSchedulersCount)
		// 给动态调度器一些时间启动，避免备用上报干扰
		return
	} else {
		logger.Info("动态监控项调度器未启动，使用硬编码上报作为备用")
	}

	// 定义基础监控项映射（作为备用机制）
	baseMetrics := []struct {
		itemID   int64
		itemKey  string
		getValue func() interface{}
	}{
		{1430255329320961, "system.cpu.util", func() interface{} { return metrics.CPU.UsagePercent }},
		{1430255329320962, "system.cpu.num", func() interface{} { return metrics.CPU.Count }},
		{1430255329320963, "vm.memory.size[total]", func() interface{} { return metrics.Memory.Total }},
		{1430255329320964, "vm.memory.util", func() interface{} { return metrics.Memory.UsagePercent }},
		{1430255329320965, "system.hostname", func() interface{} { return metrics.Host.Hostname }},
	}

	// 逐个发送指标
	successCount := 0
	for _, metric := range baseMetrics {
		value := metric.getValue()
		logger.Debugf("📊 备用上报监控项: %s = %v", metric.itemKey, value)

		resp, err := s.apiClient.SendSingleMetric(ctx, metric.itemID, value)
		if err != nil {
			logger.Errorf("备用上报监控项失败 %s: %v", metric.itemKey, err)
			continue
		}

		if resp.Code != 200 {
			logger.Errorf("备用上报监控项响应异常 %s: %s", metric.itemKey, resp.Msg)
			continue
		}

		logger.Debugf("✅ 备用上报监控项成功: %s", metric.itemKey)
		successCount++
	}

	logger.Infof("备用系统指标上报完成: 成功 %d/%d 项", successCount, len(baseMetrics))
}

// collectAndSendSNMPMetrics 采集并发送SNMP指标
func (s *Scheduler) collectAndSendSNMPMetrics() {
	s.wg.Add(1)
	defer s.wg.Done()

	ctx, cancel := context.WithTimeout(s.ctx, s.config.Agent.Timeout)
	defer cancel()

	// 采集SNMP指标
	metrics, err := s.snmpCollector.Collect(ctx)
	if err != nil {
		logger.Errorf("采集SNMP指标失败: %v", err)
		return
	}

	// 发送到HTTP服务器
	if s.config.Transport.HTTP.Enabled {
		if err := s.httpTransport.SendBatch(ctx, s.convertToInterfaceSlice(metrics), "snmp", nil); err != nil {
			logger.Errorf("发送SNMP指标到HTTP失败: %v", err)
		} else {
			logger.Debug("SNMP指标已发送到HTTP服务器")
		}
	}

	// 发送到gRPC服务器
	if s.config.Transport.GRPC.Enabled && s.grpcTransport.IsConnected() {
		if err := s.grpcTransport.SendBatch(ctx, s.convertToInterfaceSlice(metrics), "snmp", nil); err != nil {
			logger.Errorf("发送SNMP指标到gRPC失败: %v", err)
		} else {
			logger.Debug("SNMP指标已发送到gRPC服务器")
		}
	}
}

// collectAndSendScriptMetrics 采集并发送脚本执行结果
func (s *Scheduler) collectAndSendScriptMetrics() {
	s.wg.Add(1)
	defer s.wg.Done()

	ctx, cancel := context.WithTimeout(s.ctx, s.config.Agent.Timeout)
	defer cancel()

	// 执行脚本并采集结果
	metrics, err := s.scriptCollector.Collect(ctx)
	if err != nil {
		logger.Errorf("执行脚本失败: %v", err)
		return
	}

	// 发送到HTTP服务器
	if s.config.Transport.HTTP.Enabled {
		if err := s.httpTransport.SendBatch(ctx, s.convertToInterfaceSlice(metrics), "script", nil); err != nil {
			logger.Errorf("发送脚本结果到HTTP失败: %v", err)
		} else {
			logger.Debug("脚本结果已发送到HTTP服务器")
		}
	}

	// 发送到gRPC服务器
	if s.config.Transport.GRPC.Enabled && s.grpcTransport.IsConnected() {
		if err := s.grpcTransport.SendBatch(ctx, s.convertToInterfaceSlice(metrics), "script", nil); err != nil {
			logger.Errorf("发送脚本结果到gRPC失败: %v", err)
		} else {
			logger.Debug("脚本结果已发送到gRPC服务器")
		}
	}
}

// convertToInterfaceSlice 将具体类型切片转换为interface{}切片
func (s *Scheduler) convertToInterfaceSlice(slice interface{}) []interface{} {
	switch v := slice.(type) {
	case []*collector.SNMPMetrics:
		result := make([]interface{}, len(v))
		for i, item := range v {
			result[i] = item
		}
		return result
	case []*collector.ScriptMetrics:
		result := make([]interface{}, len(v))
		for i, item := range v {
			result[i] = item
		}
		return result
	default:
		return nil
	}
}

// IsRunning 检查调度器是否正在运行
func (s *Scheduler) IsRunning() bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.running
}

// GetStatus 获取调度器状态
func (s *Scheduler) GetStatus() map[string]interface{} {
	s.mu.RLock()
	defer s.mu.RUnlock()

	entries := s.cron.Entries()
	var jobCount int
	for _, entry := range entries {
		if entry.ID != 0 {
			jobCount++
		}
	}

	return map[string]interface{}{
		"running":   s.running,
		"job_count": jobCount,
		"next_run":  s.getNextRunTime(entries),
		"collectors": map[string]bool{
			"system": s.systemCollector != nil && s.systemCollector.IsEnabled(),
			"snmp":   s.snmpCollector != nil && s.snmpCollector.IsEnabled(),
			"script": s.scriptCollector != nil && s.scriptCollector.IsEnabled(),
		},
		"transporters": map[string]bool{
			"http": s.httpTransport != nil && s.httpTransport.IsEnabled(),
			"grpc": s.grpcTransport != nil && s.grpcTransport.IsEnabled(),
		},
	}
}

// getNextRunTime 获取下次运行时间
func (s *Scheduler) getNextRunTime(entries []cron.Entry) *time.Time {
	var nextRun *time.Time
	for _, entry := range entries {
		if entry.ID != 0 && (nextRun == nil || entry.Next.Before(*nextRun)) {
			nextRun = &entry.Next
		}
	}
	return nextRun
}

// startItemSchedulers 启动监控项调度器
func (s *Scheduler) startItemSchedulers() error {
	logger.Info("📋 开始启动监控项调度器...")

	if s.configManager == nil {
		logger.Warn("⚠️  配置管理器为空，跳过启动监控项调度器")
		return nil
	}

	items := s.configManager.GetItems()
	logger.Infof("📊 获取到 %d 个监控项配置", len(items))

	if len(items) == 0 {
		logger.Warn("⚠️  没有获取到任何监控项配置，可能配置尚未加载")
		return nil
	}

	// 更新命令执行采集器的监控项映射
	if s.commandCollector != nil {
		configItems := make([]client.ConfigResponseData, 0, len(items))
		for _, item := range items {
			configItems = append(configItems, client.ConfigResponseData{
				ItemID:                item.ItemID,
				ItemName:              item.ItemName,
				ItemKey:               item.ItemKey,
				InfoType:              item.InfoType,
				UpdateIntervalSeconds: item.UpdateIntervalSeconds,
				Timeout:               item.Timeout,
			})
		}
		s.commandCollector.UpdateMonitorItems(configItems)
		logger.Infof("已更新命令执行采集器的监控项映射: %d 项", len(configItems))
	}

	s.mu.Lock()
	defer s.mu.Unlock()

	for _, item := range items {
		// 确定调度模式：complex 或 simple
		mode := s.determineNewScheduleMode(item)

		logger.Infof("处理监控项: ID=%d, Name=%s, Key=%s, Mode=%s",
			item.ItemID, item.ItemName, item.ItemKey, mode)

		if len(item.Intervals) > 0 {
			logger.Infof("使用复杂intervals配置: %d 个时间窗口", len(item.Intervals))
			for i, interval := range item.Intervals {
				logger.Infof("  窗口%d: 周%d %s-%s 间隔%ds",
					i+1, interval.Week, interval.StartTime, interval.EndTime, interval.IntervalSeconds)
			}
		} else {
			logger.Infof("使用简单UpdateIntervalSeconds配置: %d", item.UpdateIntervalSeconds)
		}

		scheduler := &ItemScheduler{
			ItemID:                item.ItemID,
			ItemName:              item.ItemName,
			ItemKey:               item.ItemKey,
			InfoType:              item.InfoType,
			UpdateIntervalSeconds: item.UpdateIntervalSeconds,
			Timeout:               item.Timeout,
			Intervals:             item.Intervals,
			stopChan:              make(chan struct{}),
			running:               false,
			scheduleMode:          mode,
			currentInterval:       item.UpdateIntervalSeconds, // 默认间隔
		}

		s.itemSchedulers[item.ItemID] = scheduler

		// 根据调度模式启动
		if mode == "complex" {
			s.startComplexScheduler(scheduler)
		} else {
			s.startSimpleScheduler(scheduler)
		}

		logger.Infof("启动监控项调度器: %s (模式: %s)", item.ItemName, mode)
	}

	logger.Infof("✅ 已启动 %d 个监控项调度器", len(s.itemSchedulers))

	// 检查是否有动态调度器实际启动了
	runningSchedulers := 0
	for _, scheduler := range s.itemSchedulers {
		if scheduler.running {
			runningSchedulers++
		}
	}

	if runningSchedulers > 0 {
		logger.Infof("🎯 动态监控项调度器启动成功：%d/%d 个调度器正在运行", runningSchedulers, len(s.itemSchedulers))
	} else {
		logger.Warn("⚠️  没有动态调度器启动，系统将继续使用备用上报模式")
	}

	return nil
}

// startItemSchedulerWithTicker 使用Ticker模式启动监控项调度器
func (s *Scheduler) startItemSchedulerWithTicker(itemScheduler *ItemScheduler, duration time.Duration) {
	s.wg.Add(1)
	go func() {
		defer s.wg.Done()

		itemScheduler.ticker = time.NewTicker(duration)
		itemScheduler.running = true

		logger.Infof("启动Ticker模式监控项调度器: %s (ID: %d, 间隔: %v)",
			itemScheduler.ItemName, itemScheduler.ItemID, duration)

		for {
			select {
			case <-s.ctx.Done():
				itemScheduler.running = false
				if itemScheduler.ticker != nil {
					itemScheduler.ticker.Stop()
				}
				logger.Infof("监控项调度器停止: %s", itemScheduler.ItemName)
				return
			case <-itemScheduler.stopChan:
				itemScheduler.running = false
				if itemScheduler.ticker != nil {
					itemScheduler.ticker.Stop()
				}
				logger.Infof("监控项调度器停止: %s", itemScheduler.ItemName)
				return
			case <-itemScheduler.ticker.C:
				s.collectAndSendItem(itemScheduler)
			}
		}
	}()
}

// startItemSchedulerWithCron 使用Cron模式启动监控项调度器
func (s *Scheduler) startItemSchedulerWithCron(itemScheduler *ItemScheduler, cronExpr string) {
	itemScheduler.running = true

	// 添加cron任务
	cronID, err := s.cron.AddFunc(cronExpr, func() {
		s.collectAndSendItem(itemScheduler)
	})

	if err != nil {
		logger.Errorf("添加Cron任务失败: %s, 错误: %v", itemScheduler.ItemName, err)
		itemScheduler.running = false
		return
	}

	itemScheduler.CronID = cronID

	logger.Infof("启动Cron模式监控项调度器: %s (ID: %d, 表达式: %s, CronID: %d)",
		itemScheduler.ItemName, itemScheduler.ItemID, cronExpr, cronID)
}

// collectAndSendItem 采集并发送监控项数据
func (s *Scheduler) collectAndSendItem(itemScheduler *ItemScheduler) {
	ctx, cancel := context.WithTimeout(s.ctx, time.Duration(itemScheduler.Timeout)*time.Second)
	defer cancel()

	logger.Infof("开始采集监控项: %s (ID: %d)", itemScheduler.ItemName, itemScheduler.ItemID)

	// 根据ItemKey采集数据
	logger.Infof("正在采集数据: %s (Key: %s)", itemScheduler.ItemName, itemScheduler.ItemKey)
	value, err := s.collectItemValue(ctx, itemScheduler.ItemKey)
	if err != nil {
		logger.Errorf("采集监控项失败: %s, 错误: %v", itemScheduler.ItemName, err)
		return
	}

	logger.Infof("采集到数据: %s = %v", itemScheduler.ItemName, value)

	// 发送数据
	if s.metricsSender != nil {
		logger.Infof("正在发送数据: %s (ID: %d) = %v", itemScheduler.ItemName, itemScheduler.ItemID, value)
		err = s.metricsSender.SendMetricImmediate(ctx, itemScheduler.ItemID, value)
		if err != nil {
			logger.Errorf("发送监控项数据失败: %s, 错误: %v", itemScheduler.ItemName, err)
		} else {
			logger.Infof("✅ 发送监控项数据成功: %s (ID: %d) = %v", itemScheduler.ItemName, itemScheduler.ItemID, value)
		}
	} else {
		logger.Warn("指标发送器为空，无法发送数据")
	}
}

// collectItemValue 根据ItemKey采集指标值
func (s *Scheduler) collectItemValue(ctx context.Context, itemKey string) (interface{}, error) {
	// 按优先级顺序处理：命令映射 > 内置键 > 硬编码（向后兼容）

	// 1. 首先检查命令执行采集器（最高优先级 - 用户自定义）
	if s.commandCollector != nil && s.commandCollector.GetEnabledStatus() {
		if s.commandCollector.HasCommand(itemKey) {
			logger.Debugf("🎯 使用命令执行采集器处理: %s", itemKey)
			commands := s.commandCollector.ListCommands()
			if description, exists := commands[itemKey]; exists {
				logger.Debugf("找到命令配置: %s - %s", itemKey, description)
				// 返回一个占位值，实际值将由命令执行采集器单独发送
				return fmt.Sprintf("由命令执行采集器处理: %s", itemKey), nil
			}
		}
	}

	// 2. 然后检查内置键管理器（中等优先级 - 标准化处理）
	if s.builtinKeyManager != nil {
		if _, exists := s.builtinKeyManager.GetKey(itemKey); exists {
			logger.Debugf("🔧 使用内置键管理器处理: %s", itemKey)

			// 获取系统指标
			if s.systemCollector != nil && s.systemCollector.IsEnabled() {
				metrics, err := s.systemCollector.Collect(ctx)
				if err != nil {
					return nil, fmt.Errorf("采集系统指标失败: %v", err)
				}

				// 使用内置键管理器提取值
				value, err := s.builtinKeyManager.ExtractValue(itemKey, metrics)
				if err != nil {
					logger.Warnf("内置键管理器提取 %s 失败: %v，尝试其他方式", itemKey, err)
				} else {
					logger.Debugf("内置键管理器成功提取 %s = %v", itemKey, value)
					return value, nil
				}
			}
		}
	}

	// 3. 最后使用硬编码系统采集器（最低优先级 - 向后兼容）
	if s.systemCollector != nil && s.systemCollector.IsEnabled() {
		logger.Debugf("⚙️ 使用硬编码系统采集器（向后兼容）: %s", itemKey)
		metrics, err := s.systemCollector.Collect(ctx)
		if err != nil {
			return nil, fmt.Errorf("采集系统指标失败: %v", err)
		}

		// 硬编码的常用监控项（向后兼容）
		switch itemKey {
		case "system.cpu.util":
			logger.Debugf("硬编码处理 CPU 使用率")
			return metrics.CPU.UsagePercent, nil
		case "system.cpu.num":
			logger.Debugf("硬编码处理 CPU 核心数")
			return metrics.CPU.Count, nil
		case "vm.memory.size[total]":
			logger.Debugf("硬编码处理内存总量")
			return metrics.Memory.Total, nil
		case "vm.memory.util":
			logger.Debugf("硬编码处理内存使用率")
			return metrics.Memory.UsagePercent, nil
		case "system.hostname":
			logger.Debugf("硬编码处理主机名")
			return metrics.Host.Hostname, nil
		default:
			return nil, fmt.Errorf("不支持的监控项: %s", itemKey)
		}
	}

	return nil, fmt.Errorf("所有采集器都未启用或未找到")
}

// stopItemSchedulers 停止所有监控项调度器
func (s *Scheduler) stopItemSchedulers() {
	s.mu.Lock()
	defer s.mu.Unlock()

	for _, scheduler := range s.itemSchedulers {
		if scheduler.running {
			scheduler.running = false

			// 关闭停止通道，通知调度器停止
			close(scheduler.stopChan)

			// 停止ticker（如果有）
			if scheduler.ticker != nil {
				scheduler.ticker.Stop()
			}

			logger.Infof("停止调度器: %s (模式: %s)", scheduler.ItemName, scheduler.scheduleMode)
		}
	}

	logger.Info("所有监控项调度器已停止")
}

// onConfigUpdate 配置更新回调（确保调度器正确启动）
func (s *Scheduler) onConfigUpdate(items []services.CollectItem) {
	logger.Info("🔄 收到配置更新通知", map[string]interface{}{
		"item_count": len(items),
	})

	// 记录配置详情
	for i, item := range items {
		logger.Infof("  配置项%d: ID=%d, Name=%s, Key=%s, Interval=%ds, ComplexIntervals=%d",
			i+1, item.ItemID, item.ItemName, item.ItemKey, item.UpdateIntervalSeconds, len(item.Intervals))
	}

	// 检查当前调度器状态
	s.mu.RLock()
	currentSchedulerCount := len(s.itemSchedulers)
	s.mu.RUnlock()

	if currentSchedulerCount == 0 {
		logger.Info("📋 启动监控项调度器")
		// 启动监控项调度器
		if err := s.startItemSchedulers(); err != nil {
			logger.Errorf("❌ 启动监控项调度器失败: %v", err)
		} else {
			logger.Info("✅ 监控项调度器启动完成")
		}
	} else {
		logger.Infof("⚠️ 调度器已存在 (%d 个)，但为了确保正确运行，重新启动", currentSchedulerCount)
		
		// 停止现有调度器
		s.stopItemSchedulers()
		
		// 清空调度器映射
		s.mu.Lock()
		s.itemSchedulers = make(map[int64]*ItemScheduler)
		s.mu.Unlock()
		
		// 重新启动
		if err := s.startItemSchedulers(); err != nil {
			logger.Errorf("❌ 重新启动监控项调度器失败: %v", err)
		} else {
			logger.Info("✅ 监控项调度器重新启动完成")
		}
	}
}

// initAPIServices 初始化API服务
func (s *Scheduler) initAPIServices() error {
	// 检查是否配置了API服务
	if s.config.DeviceMonitor == nil || !s.config.DeviceMonitor.Enabled {
		logger.Info("设备监控API服务未启用，跳过初始化")
		return nil
	}

	// 创建API客户端
	clientConfig := &client.Config{
		BaseURL: s.config.DeviceMonitor.BaseURL,
		Timeout: s.config.DeviceMonitor.Timeout,
		AgentID: s.config.DeviceMonitor.AgentID,
	}
	s.apiClient = client.NewDeviceMonitorClient(clientConfig)

	// 创建注册服务
	registerService, err := services.NewRegisterService(s.apiClient, logger.GetLogger())
	if err != nil {
		return fmt.Errorf("创建注册服务失败: %v", err)
	}
	s.registerService = registerService

	// 创建心跳服务
	heartbeatConfig := &services.HeartbeatConfig{
		Interval: s.config.DeviceMonitor.HeartbeatInterval,
		Enabled:  s.config.DeviceMonitor.Enabled,
	}
	s.heartbeatService = services.NewHeartbeatService(s.apiClient, logger.GetLogger(), heartbeatConfig)

	// 创建配置管理器
	configManagerConfig := &services.ConfigManagerConfig{
		RefreshInterval: s.config.DeviceMonitor.ConfigRefreshInterval,
		Enabled:         s.config.DeviceMonitor.Enabled,
	}
	s.configManager = services.NewConfigManager(s.apiClient, logger.GetLogger(), configManagerConfig)

	// 设置配置更新回调
	s.configManager.SetConfigUpdateCallback(s.onConfigUpdate)

	// 创建指标发送器
	metricsSenderConfig := &services.MetricsSenderConfig{
		Enabled: s.config.DeviceMonitor.Enabled,
	}
	s.metricsSender = services.NewMetricsSender(s.apiClient, logger.GetLogger(), metricsSenderConfig)

	// 初始化命令执行采集器
	commandConfigPath := "configs/command_mapping.yaml"
	commandCollector, err := collector.NewCommandCollector(commandConfigPath, logger.GetLogger(), s.apiClient, s.metricsSender)
	if err != nil {
		logger.Warnf("初始化命令执行采集器失败: %v，将跳过命令执行功能", err)
		s.commandCollector = nil
	} else {
		s.commandCollector = commandCollector
		logger.Info("命令执行采集器初始化完成")
	}

	logger.Info("API服务初始化完成")
	return nil
}

// startAPIServices 启动API服务
func (s *Scheduler) startAPIServices() error {
	if s.config.DeviceMonitor == nil || !s.config.DeviceMonitor.Enabled {
		return nil
	}

	// 注册agent
	if s.registerService != nil {
		logger.Info("🔄 开始Agent注册流程...")
		if err := s.registerService.RegisterWithRetry(s.ctx, 3, 5*time.Second); err != nil {
			logger.Errorf("❌ Agent注册失败: %v", err)
			return err
		}

		// 验证注册结果
		if s.apiClient.GetAgentID() != "" {
			logger.Infof("✅ Agent注册成功, AgentID: %s", s.apiClient.GetAgentID())
			if s.apiClient.GetToken() != "" {
				logger.Info("✅ 认证Token已获取")
			} else {
				logger.Warn("⚠️  认证Token为空，可能影响API调用")
			}
		} else {
			logger.Error("❌ Agent注册失败: 未获取到AgentID")
			return fmt.Errorf("注册失败：未获取到AgentID")
		}
	}

	// 启动心跳服务
	if s.heartbeatService != nil {
		if err := s.heartbeatService.Start(s.ctx); err != nil {
			logger.Errorf("启动心跳服务失败: %v", err)
			return err
		}
	}

	// 启动配置管理器
	if s.configManager != nil {
		if err := s.configManager.Start(s.ctx); err != nil {
			logger.Errorf("启动配置管理器失败: %v", err)
			return err
		}
	}

	// 启动指标发送器
	if s.metricsSender != nil {
		if err := s.metricsSender.Start(s.ctx); err != nil {
			logger.Errorf("启动指标发送器失败: %v", err)
			return err
		}
	}

	logger.Info("API服务启动完成")
	return nil
}

// stopAPIServices 停止API服务
func (s *Scheduler) stopAPIServices() {
	if s.config.DeviceMonitor == nil || !s.config.DeviceMonitor.Enabled {
		return
	}

	// 停止指标发送器
	if s.metricsSender != nil {
		if err := s.metricsSender.Stop(); err != nil {
			logger.Errorf("停止指标发送器失败: %v", err)
		}
	}

	// 停止配置管理器
	if s.configManager != nil {
		if err := s.configManager.Stop(); err != nil {
			logger.Errorf("停止配置管理器失败: %v", err)
		}
	}

	// 停止心跳服务
	if s.heartbeatService != nil {
		if err := s.heartbeatService.Stop(); err != nil {
			logger.Errorf("停止心跳服务失败: %v", err)
		}
	}

	logger.Info("API服务已停止")
}

// parseIntervals 解析intervals字段，返回调度模式和相应的配置
// 支持的格式：
// 1. "30s" -> ticker模式，30秒间隔
// 2. "1m" -> ticker模式，1分钟间隔
// 3. "*/30 * * * * *" -> cron模式，每30秒执行
// 4. "0 */5 * * * *" -> cron模式，每5分钟执行
func parseIntervals(intervals *string, fallbackSeconds int) (mode string, duration time.Duration, cronExpr string, err error) {
	// 如果intervals为空或nil，使用fallbackSeconds
	if intervals == nil || strings.TrimSpace(*intervals) == "" {
		if fallbackSeconds <= 0 {
			fallbackSeconds = 30 // 默认30秒
		}
		return "ticker", time.Duration(fallbackSeconds) * time.Second, "", nil
	}

	intervalStr := strings.TrimSpace(*intervals)

	// 检查是否是时间间隔格式 (如: 30s, 1m, 2h)
	if durationRegex := regexp.MustCompile(`^(\d+)([smhd])$`); durationRegex.MatchString(intervalStr) {
		duration, err := parseDuration(intervalStr)
		if err != nil {
			return "", 0, "", fmt.Errorf("解析时间间隔失败: %v", err)
		}
		return "ticker", duration, "", nil
	}

	// 检查是否是cron表达式格式
	if isCronExpression(intervalStr) {
		return "cron", 0, intervalStr, nil
	}

	// 如果都不匹配，尝试作为纯数字处理（秒）
	if seconds, err := strconv.Atoi(intervalStr); err == nil && seconds > 0 {
		return "ticker", time.Duration(seconds) * time.Second, "", nil
	}

	return "", 0, "", fmt.Errorf("不支持的intervals格式: %s", intervalStr)
}

// parseDuration 解析自定义的时间间隔格式
func parseDuration(intervalStr string) (time.Duration, error) {
	re := regexp.MustCompile(`^(\d+)([smhd])$`)
	matches := re.FindStringSubmatch(intervalStr)
	if len(matches) != 3 {
		return 0, fmt.Errorf("invalid duration format: %s", intervalStr)
	}

	value, err := strconv.Atoi(matches[1])
	if err != nil {
		return 0, fmt.Errorf("invalid number: %s", matches[1])
	}

	unit := matches[2]
	switch unit {
	case "s":
		return time.Duration(value) * time.Second, nil
	case "m":
		return time.Duration(value) * time.Minute, nil
	case "h":
		return time.Duration(value) * time.Hour, nil
	case "d":
		return time.Duration(value) * 24 * time.Hour, nil
	default:
		return 0, fmt.Errorf("unsupported time unit: %s", unit)
	}
}

// isCronExpression 检查字符串是否是有效的cron表达式
func isCronExpression(expr string) bool {
	// 简单检查：包含空格且有5-6个字段
	fields := strings.Fields(expr)
	if len(fields) < 5 || len(fields) > 6 {
		return false
	}

	// 更严格的cron格式验证可以在这里添加
	// 现在只做基本验证
	for _, field := range fields {
		if field == "" {
			return false
		}
	}

	return true
}

// determineNewScheduleMode 确定新的调度模式
func (s *Scheduler) determineNewScheduleMode(item services.CollectItem) string {
	// 如果有复杂的intervals配置，使用complex模式
	if len(item.Intervals) > 0 {
		return "complex"
	}

	// 否则使用simple模式
	return "simple"
}

// startComplexScheduler 启动复杂调度器（支持时间窗口）
func (s *Scheduler) startComplexScheduler(itemScheduler *ItemScheduler) {
	s.wg.Add(1)
	go func() {
		defer s.wg.Done()

		// 使用1分钟的检查间隔，用于检测时间窗口切换
		checkTicker := time.NewTicker(1 * time.Minute)
		defer checkTicker.Stop()

		var dataTicker *time.Ticker
		itemScheduler.running = true

		logger.Infof("启动复杂调度器: %s (ID: %d)", itemScheduler.ItemName, itemScheduler.ItemID)

		// 初始检查并设置合适的数据采集间隔
		s.updateComplexSchedulerInterval(itemScheduler, &dataTicker)

		for {
			select {
			case <-s.ctx.Done():
				itemScheduler.running = false
				if dataTicker != nil {
					dataTicker.Stop()
				}
				logger.Infof("复杂调度器停止: %s", itemScheduler.ItemName)
				return
			case <-itemScheduler.stopChan:
				itemScheduler.running = false
				if dataTicker != nil {
					dataTicker.Stop()
				}
				logger.Infof("复杂调度器停止: %s", itemScheduler.ItemName)
				return
			case <-checkTicker.C:
				// 每分钟检查一次时间窗口变化
				s.updateComplexSchedulerInterval(itemScheduler, &dataTicker)
			case <-func() <-chan time.Time {
				if dataTicker != nil {
					return dataTicker.C
				}
				return make(<-chan time.Time) // 返回永远不会触发的channel
			}():
				// 执行数据采集
				s.collectAndSendItem(itemScheduler)
			}
		}
	}()
}

// startSimpleScheduler 启动简单调度器（固定间隔）
func (s *Scheduler) startSimpleScheduler(itemScheduler *ItemScheduler) {
	s.wg.Add(1)
	go func() {
		defer s.wg.Done()

		duration := time.Duration(itemScheduler.UpdateIntervalSeconds) * time.Second
		itemScheduler.ticker = time.NewTicker(duration)
		itemScheduler.running = true

		logger.Infof("🚀 启动简单调度器: %s (ID: %d, 间隔: %ds = %v)",
			itemScheduler.ItemName, itemScheduler.ItemID, itemScheduler.UpdateIntervalSeconds, duration)

		for {
			select {
			case <-s.ctx.Done():
				itemScheduler.running = false
				if itemScheduler.ticker != nil {
					itemScheduler.ticker.Stop()
				}
				logger.Infof("⛔ 简单调度器停止: %s", itemScheduler.ItemName)
				return
			case <-itemScheduler.stopChan:
				itemScheduler.running = false
				if itemScheduler.ticker != nil {
					itemScheduler.ticker.Stop()
				}
				logger.Infof("⛔ 简单调度器停止: %s", itemScheduler.ItemName)
				return
			case <-itemScheduler.ticker.C:
				logger.Debugf("⏰ 简单调度器触发: %s (间隔: %ds)",
					itemScheduler.ItemName, itemScheduler.UpdateIntervalSeconds)
				s.collectAndSendItem(itemScheduler)
			}
		}
	}()
}

// updateComplexSchedulerInterval 更新复杂调度器的采集间隔
func (s *Scheduler) updateComplexSchedulerInterval(itemScheduler *ItemScheduler, dataTicker **time.Ticker) {
	now := time.Now()
	currentWeekday := s.convertWeekday(now.Weekday())
	currentTime := now.Format("15:04:05")

	logger.Debugf("检查监控项 %s 的时间窗口: 当前时间=%s 星期%d",
		itemScheduler.ItemName, currentTime, currentWeekday)

	// 检查当前是否在任何时间窗口内
	activeInterval := s.getActiveInterval(itemScheduler.Intervals, now)

	newInterval := itemScheduler.UpdateIntervalSeconds // 默认间隔
	if activeInterval != nil {
		newInterval = activeInterval.IntervalSeconds
		logger.Debugf("监控项 %s 匹配到时间窗口: 周%d %s-%s 间隔%ds",
			itemScheduler.ItemName, activeInterval.Week,
			activeInterval.StartTime, activeInterval.EndTime, activeInterval.IntervalSeconds)
	} else {
		logger.Debugf("监控项 %s 未匹配任何时间窗口，使用默认间隔: %ds",
			itemScheduler.ItemName, newInterval)
	}

	// 如果间隔发生变化，重新创建ticker
    if newInterval != itemScheduler.currentInterval || *dataTicker == nil {
		logger.Infof("⏰ 监控项 %s 间隔变化: %ds -> %ds",
			itemScheduler.ItemName, itemScheduler.currentInterval, newInterval)

		// 停止旧的ticker
		if *dataTicker != nil {
			(*dataTicker).Stop()
		}

		// 创建新的ticker
		*dataTicker = time.NewTicker(time.Duration(newInterval) * time.Second)
		itemScheduler.currentInterval = newInterval

		if activeInterval != nil {
			logger.Infof("🎯 监控项 %s 进入时间窗口: 周%s %s-%s 间隔%ds",
				itemScheduler.ItemName, activeInterval.WeekStr,
				activeInterval.StartTime, activeInterval.EndTime, activeInterval.IntervalSeconds)
		} else {
			logger.Infof("📅 监控项 %s 使用默认间隔: %ds",
				itemScheduler.ItemName, newInterval)
		}
	} else {
		logger.Debugf("监控项 %s 间隔无变化，保持: %ds", itemScheduler.ItemName, newInterval)
	}
}

// getActiveInterval 获取当前时间点的活跃时间窗口
func (s *Scheduler) getActiveInterval(intervals []services.IntervalSchedule, now time.Time) *services.IntervalSchedule {
	currentWeekday := s.convertWeekday(now.Weekday())
	currentTime := now.Format("15:04:05")

    for _, interval := range intervals {
        if s.isInTimeWindowWithWeek(interval, currentWeekday, currentTime) {
            return &interval
        }
    }

	return nil
}

// convertWeekday 转换Go的Weekday到我们的格式 (1-7: 1=周一, 7=周日)
func (s *Scheduler) convertWeekday(goWeekday time.Weekday) int {
	// Go: Sunday = 0, Monday = 1, ..., Saturday = 6
	// 我们: Monday = 1, Tuesday = 2, ..., Sunday = 7
	if goWeekday == time.Sunday {
		return 7
	}
	return int(goWeekday)
}

// isInTimeWindow 检查当前时间是否在指定的时间窗口内
func (s *Scheduler) isInTimeWindow(interval services.IntervalSchedule, currentWeekday int, currentTime string) bool {
	// 检查时间范围即可，不用处理weekStr
	inRange := s.isTimeInRange(currentTime, interval.StartTime, interval.EndTime)
	if inRange {
		logger.Debugf("  ✅ 时间窗口匹配: %s-%s, 当前时间=%s",
			interval.StartTime, interval.EndTime, currentTime)
	} else {
		logger.Debugf("  ❌ 时间窗口时间不匹配: %s-%s, 当前时间=%s",
			interval.StartTime, interval.EndTime, currentTime)
	}
	return inRange
}

// isTimeInRange 检查时间是否在指定范围内（支持跨日）
func (s *Scheduler) isTimeInRange(currentTime, startTime, endTime string) bool {
	// 解析时间字符串为可比较的格式
	current := s.parseTimeToMinutes(currentTime)
	start := s.parseTimeToMinutes(startTime)
	end := s.parseTimeToMinutes(endTime)

	if start <= end {
		// 不跨日的情况: 如 09:00:00 到 17:00:00
		return current >= start && current <= end
	} else {
		// 跨日的情况: 如 23:00:00 到 01:00:00
		return current >= start || current <= end
	}
}

// parseTimeToMinutes 将时间字符串转换为当日秒数（提高精度）
func (s *Scheduler) parseTimeToMinutes(timeStr string) int {
	parts := strings.Split(timeStr, ":")
	if len(parts) != 3 {
		logger.Warnf("无效的时间格式: %s", timeStr)
		return 0
	}

	hour, _ := strconv.Atoi(parts[0])
	minute, _ := strconv.Atoi(parts[1])
	second, _ := strconv.Atoi(parts[2])

	// 返回当日总秒数，提高时间比较精度
	return hour*3600 + minute*60 + second
}

// isInTimeWindowWithWeek 周+时间窗口判断（支持 week 与 weekStr）
func (s *Scheduler) isInTimeWindowWithWeek(interval services.IntervalSchedule, currentWeekday int, currentTime string) bool {
    // 先按周判断（1-7: 1=周一, 7=周日）。
    weekMatch := false

    if interval.Week >= 1 && interval.Week <= 7 {
        weekMatch = (interval.Week == currentWeekday)
    } else if strings.TrimSpace(interval.WeekStr) != "" {
        // 支持 weekStr: "1-7", "1,3,5", 或组合如 "1-5,7"
        parts := strings.Split(interval.WeekStr, ",")
        for _, p := range parts {
            p = strings.TrimSpace(p)
            if p == "" {
                continue
            }
            if strings.Contains(p, "-") {
                rng := strings.SplitN(p, "-", 2)
                if len(rng) == 2 {
                    start, err1 := strconv.Atoi(strings.TrimSpace(rng[0]))
                    end, err2 := strconv.Atoi(strings.TrimSpace(rng[1]))
                    if err1 == nil && err2 == nil {
                        if start <= end {
                            if currentWeekday >= start && currentWeekday <= end {
                                weekMatch = true
                                break
                            }
                        } else { // 跨范围，如 6-2 表示 6,7,1,2
                            if currentWeekday >= start || currentWeekday <= end {
                                weekMatch = true
                                break
                            }
                        }
                    }
                }
            } else {
                if v, err := strconv.Atoi(p); err == nil && v == currentWeekday {
                    weekMatch = true
                    break
                }
            }
        }
    } else {
        // 未配置周信息，视为每天都匹配
        weekMatch = true
    }

    if !weekMatch {
        logger.Debugf("  星期不匹配: week=%d weekStr=%s 当前=%d", interval.Week, interval.WeekStr, currentWeekday)
        return false
    }

    // 再按时间窗口判断（支持跨日）
    inRange := s.isTimeInRange(currentTime, interval.StartTime, interval.EndTime)
    if inRange {
        logger.Debugf("  时间窗口匹配: %s-%s, 当前=%s", interval.StartTime, interval.EndTime, currentTime)
    } else {
        logger.Debugf("  时间窗口不匹配: %s-%s, 当前=%s", interval.StartTime, interval.EndTime, currentTime)
    }
    return inRange
}
